package jamirr;

final class StringIntMap {

    private final int mask;
    private final String[] keys;
    private final int[] values;

    /**
     * 创建一个新的映射。给定的大小<b>不能</b>被{@link #put}操作超过，
     * 否则可能会导致无限循环。出于性能原因，这里没有进行健全性检查！
     *
     * @param size 映射的最大大小
     */
    public StringIntMap(int size) {
        // 最小大小：至少一个槽位，目标为50%的负载因子
        int tableSize = (size * 2) + 1;
        // 四舍五入到下一个2的幂，以便高效的哈希码掩码
        tableSize = Integer.highestOneBit(tableSize) * 2;
        this.mask = tableSize - 1;
        this.keys = new String[tableSize];
        this.values = new int[keys.length];
    }

    private int probe(String key) {
        int n = keys.length;
        int i = key.hashCode() & mask;
        while (true) {
            String candidate = keys[i];
            if (candidate == null) {
                return ~i;
            } else if (candidate.equals(key)) {
                return i;
            } else {
                i++;
                if (i == n) {
                    i = 0;
                }
            }
        }
    }

    public int get(String key, int def) {
        int i = probe(key);
        return i < 0 ? def : values[i];
    }

    public void put(String key, int value) {
        int tableIndex = ~probe(key);
        if (tableIndex < 0) {
            throw new IllegalArgumentException("Duplicate key");
        }
        keys[tableIndex] = key;
        values[tableIndex] = value;
    }
}
